<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>


    <!-- EventTarget.addEventListener() -->
    <!-- https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener -->
    <!-- EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上，当该对象触发指定的事件时，指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element,Document和Window或者任何其他支持事件的对象 (比如 XMLHttpRequest)。 -->
    <!-- target.addEventListener(type, listener, useCapture); -->
    <!-- type 表示监听事件类型的字符串。 -->
    <!-- listener 当所监听的事件类型触发时，会接收到一个事件通知（实现了 Event 接口的对象）对象。listener 必须是一个实现了 EventListener 接口的对象，或者是一个函数。 -->
    <!-- useCapture 可选 Boolean，在DOM树中，注册了listener的元素， 是否要先于它下面的EventTarget，调用该listener。 当useCapture(设为true) 时，沿着DOM树向上冒泡的事件，不会触发listener。当一个元素嵌套了另一个元素，并且两个元素都对同一事件注册了一个处理函数时，所发生的事件冒泡和事件捕获是两种不同的事件传播方式。事件传播模式决定了元素以哪个顺序接收事件。 -->

    <p>验证事件传递和事件阶段</p>
    <div id="container_1" style="padding: 10%; background-color: red; margin: 10%">
        1级父容器
        <div id="container_2" style="padding: 10%; background-color: green;">
            2级父容器
            <div id="element" style="padding: 10%; background-color: blue;">
                在这里验证点击事件的事件传递路径和冒泡过程
                <div id="child" style="padding: 10%; background-color: orange;">
                    子元素
                </div>
            </div>
        </div>
    </div>
    <script>
        var container_1 = document.getElementById('container_1');
        var container_2 = document.getElementById('container_2');
        var element = document.getElementById('element');
        var child = document.getElementById('child');

        var useCapture = false;
        container_1.addEventListener('click', function (event) {
            console.log('container_1. click. ' + new Date());
        }, useCapture);
        container_2.addEventListener('click', function (event) {
            console.log('container_2. click. ' + new Date());
        }, useCapture);
        element.addEventListener('click', function (event) {
            console.log('element. click. ' + new Date());
        }, useCapture);
        child.addEventListener('click', function (event) {
            console.log('child. click. ' + new Date());
        }, useCapture);

        // 期望输出
        // 由于事件传播只是从父元素到目标元素之间传播，child元素不在事件传播路径中，故child元素的click事件监听器不会被执行。
        // 1. 如果“useCapture = false”，非捕获，即冒泡阶段，那么输出依次是：element, container_2, container_1。
        // 1. 如果“useCapture = true”，捕获，即捕获阶段阶段，那么输出依次是：container_1, container_2, element。
    </script>

</body>

</html>

<!-- 事件介绍 -->
<!-- https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Building_blocks/Events -->
<!-- 事件是您在编程时系统内发生的动作或者发生的事情，系统响应事件后，如果需要，您可以某种方式对事件做出回应。例如：如果用户在网页上单击一个按钮，您可能想通过显示一个信息框来响应这个动作。 -->
<!-- 事件参考 -->
<!-- https://developer.mozilla.org/zh-CN/docs/Web/Events -->
<!-- 发送DOM事件是为了将发生的相关事情通知代码。每个事件都是继承自Event 接口的对象，可以包括自定义的成员属性及函数用于获取事件发生时相关的更多信息。事件可以表示任何从基本的用户交互、到发生在渲染模型自动通知的任何事情。 -->
<!-- 注：从上面链接查询事件列表 -->


<!-- 使用网页事件的方式 -->

<!-- 事件处理器属性 -->
<!-- 一些事件非常通用，几乎在任何地方都可以用（比如 onclick 几乎可以用在几乎每一个元素上），然而另一些元素就只能在特定场景下使用，比如我们只能在 video 元素上使用 onplay 。 -->

<!-- 行内事件处理器 - 请勿使用 -->
<!-- 在Web上注册事件处理程序的最早方法是类似于上面所示的事件处理程序HTML属性(也称为内联事件处理程序)—属性值实际上是当事件发生时要运行的JavaScript代码。 -->
<!-- 使用一个事件处理属性似乎看起来很简单，如果你只是在做一些非常快的事情，但很快就变得难以管理和效率低下。 -->

<!-- addEventListener() 和removeEventListener() -->
<!-- 新的事件触发机制被定义在 Document Object Model (DOM) Level 2 Events Specification, 这个细则给浏览器提供了一个函数 — addEventListener()。这个函数和事件处理属性是类似的，但是语法略有不同。 -->